﻿using HslCommunication;
using HslCommunication.Core;
using HslCommunication.Profinet.Siemens;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Channels;
using System.Threading.Tasks;
using ZhonTai.Industry.Contracts.Core.Enums;
using ZhonTai.Industry.Contracts.Model.Entity;

namespace ZhonTai.Industry.Contracts.Communication
{
    /// <summary>
    /// 西门子PLC
    /// </summary>
    public sealed class SiemensPlc : SiemensS7Net
    {
        // 异步锁对象
        private readonly SemaphoreSlim _asyncLock = new SemaphoreSlim(1, 1);

        public SiemensPlc(SiemensPLCS siemens, string ip, int port, int rack, int slot) : base(siemens)
        {
            base.IpAddress = ip;
            base.Port = port;
            base.ConnectTimeOut = 3000;
            base.ReceiveTimeOut = 3000;
            base.SetPersistentConnection();
        }

        #region Write

        public override async Task<OperateResult> WriteAsync(string address, short value)
        {
            await _asyncLock.WaitAsync();
            try
            {
                return await base.WriteAsync(address, value);
            }
            finally
            {
                _asyncLock.Release();
            }
        }

        public override async Task<OperateResult> WriteAsync(string address, float value)
        {
            await _asyncLock.WaitAsync();
            try
            {
                return await base.WriteAsync(address, value);
            }
            finally
            {
                _asyncLock.Release();
            }
        }

        public override async Task<OperateResult> WriteAsync(string address, string value)
        {
            await _asyncLock.WaitAsync();
            try
            {
                return await base.WriteAsync(address, value);
            }
            finally
            {
                _asyncLock.Release();
            }
        }

        #endregion Write

        #region Read

        public override async Task<OperateResult<byte[]>> ReadAsync(string address, ushort length)
        {
            await _asyncLock.WaitAsync();
            try
            {
                return await base.ReadAsync(address, length);
            }
            finally
            {
                _asyncLock.Release();
            }
        }

        public new async Task<OperateResult<short>> ReadInt16Async(string address)
        {
            return ByteTransformHelper.GetResultFromArray(await base.ReadInt16Async(address, 1));
        }

        public new async Task<OperateResult<float>> ReadFloatAsync(string address)
        {
            return ByteTransformHelper.GetResultFromArray(await base.ReadFloatAsync(address, 1));
        }

        public new async Task<OperateResult<string>> ReadStringAsync(string address)
        {
            return await base.ReadStringAsync(address, Encoding.ASCII);
        }

        #endregion Read
    }
}